#ifndef _ENGINE_GAME_HPP
#define _ENGINE_GAME_HPP

#include "../common.hpp"

namespace yep
{
    class Scene;    //Foward declarations
    class Screen;   //Foward declarations

    /**
     * @brief The main game class @b [singleton].
     */
    class Game
    {
    public:
        /**
         * @brief Destructor
         **/
        virtual ~Game();

        //Getters and setters
        /**
         * @brief Returns fps
         */
        unsigned getFps() const
        {
            return fps;
        }

        /**
         * @brief Changes fps
         */
        void setFps(unsigned value)
        {
            fps = value;
        }

        /**
         * @brief Returns currentFrame number
         */
        unsigned getCurrentFrame() const
        {
            return currentFrame;
        }

        /**
         * @brief Returns running
         */
        bool isRunning() const
        {
            return running;
        }

        /**
         * @brief Returns currentScene
         */
        Scene &getCurrentScene() const
        {
            return *currentScene;
        }

        /**
         * @brief Changes currentScene
         */
        void setCurrentScene(Scene &value)
        {
            currentScene = &value;
        }

        /**
         * @brief Returns the showFPS
         **/
        bool isShowFPS( void ) const
        {
            return showFPS;
        }

        /**
         * @brief Changes the showFPS
         **/
        void setShowFPS( bool value )
        {
            showFPS = value;
        }

        /**
         * @brief Returns instance
         */
        static Game &getInstance()
        {
            if(instance)
                return *instance;
            else
                return *(instance = new Game);
        }

        //Methods

        void exit()
        {
            running = false;
        }


        /**
         * @brief Runs the game.
         *
         * It assumes that the SDL (and any other related library like SDL_TTF) was already
         *  initialized, checking only if the Screen exists, and creating a new one if
         *  needed. This is probably the last method called on the main() function on code,
         *  because it controls the program flows and only exit when the program ends. It also
         *  expects you define a scene before this calling.
         *
         * The algorithm peformed is like this:
         *
         * -# If there isn't a @b screen, it instantiates a new Screen;
         * -# Executes the Scene::setup() to @b currentScene;
         * -# Sets @b running to true;
         * -# Call Scene::logic() to @b currentScene;
         * -# Call Scene::draw() to @b currentScene;
         * -# If @b currentScene is changed:
         *      -# Call Scene::cleanup() to the old one;
         *      -# Call Scene::setup() to the new one;
         * -# If @b running is true, goto step 4;
         * -# Sets @b running to false;
         * -# Else Call Scene::cleanup() to @b currentScene;
         *
         * @return true if everything ended ok, false if a error occured.
         **/
        bool run();

    protected:
        /**
         * @brief contructor.
         *
         * Non-public to implement a singleton interface.
         **/
        Game();

        /**
         * @brief Draw the fps on screen
         **/
        virtual void drawFPS(unsigned fps);
    private:
        unsigned fps;
        unsigned currentFrame;
        bool running;
        bool showFPS;
        Scene *currentScene;
        static Game *instance;
    };

}

#endif // _ENGINE_GAME_HPP
